CloudWatch エージェントの StatsD プロトコルを利用して Windows のサービス監視を実施する仕組みを構築してみた
こんにちは。テクニカルサポートチームのShiinaです。
はじめに
Windows のサービス監視を CloudWatch で実施できたらいいなと思ったことはありませんか?
プロセス監視の場合、procstat プラグインを利用することができますが、サービス監視用のプラグインは用意されていません。
そのため、Windows のサービス監視を行うには独自にカスタムメトリクスを put するようなスクリプトを用意してメトリクスを収集する必要があります。
今回、CloudWatch エージェントの StatsD プロトコルを利用し、サービスの状態を示すカスタムメトリクスを送信する仕組みを構築して、サービス監視を実施してみました。
概要
CloudWatch エージェントで StatsD プロトコルを利用し、メトリクスを受信できるように設定します。
StatsD クライアントは Node.js の Node-Statsd を利用します。
Node-Statsd ライブラリを利用して Windows のサービス状態を示すメトリクスをスクリプトで送信します。
スクリプトはタスクスケジューラを利用することでシステム起動時に自動実行できるようにします。
収集したカスタムメトリクスに対して CloudWatch アラームを設定し、サービス監視を実施します。
StatsD とは
アプリケーションやシステムのパフォーマンスを監視・計測するために使用される軽量なメトリクス収集ツールです。
デーモン(常駐プログラム)であり、アプリケーションやサービスから送信される様々なパフォーマンスデータ(メトリクス)を受け取り、集計・処理する役割を果たします。
UDP プロトコルを使用しているため、軽量かつ高速にデータを送信します。
前提
- Windows の EC2 インスタンスに CloudWatch エージェントのインストールされていること
- CloudWatch エージェントが CloudWatch にメトリクスを書き込むために必要なアクセスが許可されていること
今回利用した EC2 のインスタンスロールは AWS マネージドポリシー「CloudWatchAgentServerPolicy」を利用しています。
設定の流れ
設定の流れは以下の通りです。
- CloudWatch エージェントの設定
config.json ファイルを編集し、StatsD プロトコルでメトリクスを受信できるように設定します。 - Node.js とライブラリのインストール
Node.js をインストールし、必要なライブラリ(node-statsd と yargs)をインストールします。 - スクリプト配置と動作確認
サービスの状態を取得し、StatsD にメトリクスを送信するスクリプトを作成し、動作を確認します。 - タスクスケジューラ登録
タスクスケジューラにタスクを登録して、システム起動時にスクリプトを自動実行できるようにします。 - CloudWatch アラーム設定
サービスの状態に基づいてアラームを設定し、異常時に通知を受け取るようにします。
設定手順
1.CloudWatch エージェントの設定
Cloudwatch エージェントの設定を行うため、config.json ファイルを修正します。
設定するパラメータは次の通りです。
パラメータ | 設定値 | 説明 |
---|---|---|
service_address | 8125 | StatsDリッスンポートを指定します。デフォルトポート8125を利用します。 |
metrics_collection_interval | 60 | メトリクスの収集頻度を指定します。60秒ごとにサービスのステータスメトリクスを収集します。 |
metrics_aggregation_interval | 60 | 1 つのデータポイントにメトリクスを集約する頻度を指定します。デフォルトの60秒を利用します。 |
append_dimensions | InstanceId と ServiceName | 一意に識別できるよう、インスタンス ID とサービス名をディメンションに追加します。 |
{
"metrics": {
"metrics_collected": {
"statsd": {
"service_address": ":8125",
"metrics_collection_interval": 60,
"metrics_aggregation_interval": 60,
}
},
"append_dimensions": {
"InstanceId": "${aws:InstanceId}",
"ServiceName": "${service}"
}
}
}
設定ファイルの反映を行います。
cd "C:\Program Files\Amazon\AmazonCloudWatchAgent"
.\amazon-cloudwatch-agent-ctl.ps1 -a fetch-config -m ec2 -c file:"C:\ProgramData\Amazon\AmazonCloudWatchAgent\config.json" -s
****** processing amazon-cloudwatch-agent ******
I! Trying to detect region from ec2
D! [EC2] Found active network interface
I! imds retry client will retry 1 timesSuccessfully fetched the config and saved in C:\ProgramData\Amazon\AmazonCloudWatchAgent\Configs\file_config.json.tmp
Start configuration validation...
2024/10/15 08:53:46 Reading json config file path: C:\ProgramData\Amazon\AmazonCloudWatchAgent\Configs\file_config.json.tmp ...
2024/10/15 08:53:46 I! Valid Json input schema.
I! Trying to detect region from ec2
D! [EC2] Found active network interface
I! imds retry client will retry 1 times2024/10/15 08:53:46 D! ec2tagger processor required because append_dimensions is set
2024/10/15 08:53:46 Configuration validation first phase succeeded
Configuration validation second phase succeeded
Configuration validation succeeded
AmazonCloudWatchAgent has been stopped
AmazonCloudWatchAgent has been started
2.Node.js とライブラリのインストール
下記 URL より Node.js の msi ファイルをダウンロードします。
ダウンロードした msi ファイルを実行し、ウィザードに従ってインストールを行います。
インストールが完了するまで待ちます。
スタートメニューより Node.js フォルダの「Node.js command prompt」を実行します。
ライブラリのインストール先およびスクリプトを配置するためのフォルダを作成します。
mkdir "C:\CustomMetricsCollector"
cd "C:\CustomMetricsCollector"
必要ライブラリのインストールを行います。
npm install node-statsd yargs
次のようなファイル構成となっていればライブラリのインストールは完了です。
3.スクリプト配置
下記スクリプトをコピー&ペーストとして js ファイルとして保存します。
C:\CustomMetricsCollector\WindowsServiceStatusMetricsCollector.js がファイルパスになるように配置を行います。
// WindowsServiceStatusMetricsCollector.js
const { StatsD } = require('node-statsd');
const { exec } = require('child_process');
const yargs = require('yargs');
// 設定
const STATSD_HOST = 'localhost';
const STATSD_PORT = 8125;
const METRIC_NAME = 'windows_services_status'; // メトリクス名
const COLLECTION_INTERVAL = 60000; // 60秒
// コマンドライン引数の設定
const argv = yargs
.option('services', {
alias: 's',
description: '監視対象のサービス名をスペース区切りで指定',
type: 'array',
demandOption: true
})
.help()
.argv;
// StatsDクライアントの設定
const client = new StatsD({
host: STATSD_HOST,
port: STATSD_PORT
});
/**
* 指定されたサービスの状態を取得します。
* @param {string} serviceName - サービス名
* @returns {Promise<number>} - 起動中:1, 停止中:0
*/
function getServiceStatus(serviceName) {
return new Promise((resolve) => {
// sc query コマンドを使用してサービスの状態を取得
exec(`sc query "${serviceName}"`, (error, stdout, stderr) => {
// SERVICE_RUNNING のステータスは "RUNNING" と表示される
const running = stdout.includes('RUNNING');
resolve(running ? 1 : 0);
});
});
}
/**
* サービスの状態を監視し、StatsDにメトリクスを送信します。
*/
async function collector() {
for (const serviceName of argv.services) {
const status = await getServiceStatus(serviceName);
const tags = [`service:${serviceName}`]; // タグとしてサービス名を追加
client.gauge(METRIC_NAME, status, tags);
console.log(`メトリック送信: ${METRIC_NAME}=${status} | tags=${tags.join(',')}`);
}
}
// コレクション間隔でステータス確認を実行
setInterval(collector, COLLECTION_INTERVAL);
// 初回実行
collector();
次のようなファイル構成となっていればスクリプトの配置は完了です。
4.スクリプト動作確認
スタートメニューより Node.js フォルダの「Node.js command prompt」を実行します。
スクリプトを保存したフォルダーを移動し、引数にメトリクスを収集したいサービス名を指定してスクリプトを実行します。
W32Time、Spooler、Dhcp、W3SVC サービスを指定した場合のコマンドは次の通りです。
cd "C:\CustomMetricsCollector"
node WindowsServiceStatusMetricsCollector.js --services W32Time Spooler Dhcp W3SVC
メトリック送信が行われたログが出力されることを確認します。
C:\CustomMetricsCollector>node WindowsServiceStatusMetricsCollector.js --services W32Time Spooler Dhcp W3SVC
メトリック送信: windows_services_status=1 | tags=service:W32Time
メトリック送信: windows_services_status=0 | tags=service:Spooler
メトリック送信: windows_services_status=1 | tags=service:Dhcp
メトリック送信: windows_services_status=1 | tags=service:W3SVC
5.メトリクス確認
CloudWatch サービスのメニューよりメトリクスのすべてのメトリクスを選択します。
カスタム名前空間「CWAgent」を選択し、ディメンション「InstanceId,metric_type,service」を選択します。
メトリクス名「windows_services_status」として、サービスごとのメトリクスの値が表示されていることを確認します。
上記のメトリクスはサービスが起動中の状態であれば 1 、それ以外の状態では 0 の値が記録されます。
6.タスクスケジューラ登録
タスクスケジューラを起動し、タスクスケジューラライブラリを選択の上、「タスクの作成」をクリックします。
トリガータブを選択し、「新規」をクリックします。
タスクの開始でスタートアップ時を選択し、「OK」をクリックします。
操作タブを選択し、「新規」をクリックします。
操作ではプログラムの開始を選択し、設定項目にそれぞれ下記の値を入力の上、「OK」をクリックします。
-
プログラム/スクリプト
"C:\Program Files\nodejs\node.exe" -
引数の追加
"C:\CustomMetricsCollector\WindowsServiceStatusMetricsCollector.js" --services W32Time Spooler Dhcp W3SVC -
開始
"C:\CustomMetricsCollector"
全般タブを選択し、任意のタスク名を入力します。
セキュリティオプションでは「ユーザがログオンしているかどうかにかかわらず実行する」および「最上位の特権で実行する」にチェックを入れ、「OK」をクリックします。
Administrator のパスワードを入力して「OK」をクリックします。
7.タスクの動作確認
タスク名を右クリックし、「実行する」をクリックします。
タスクの状態が「実行中」、前回の実行結果が「現在タスクを実行中です」と表示され、
プロセス一覧に「Node.js JavaScript Runtime」が表示されていれば正しくスクリプトが実行されています。
可能なら、EC2 インスタンスを再起動し、起動後にスクリプトが正しく実行されているか確認してください。
8.アラーム設定
CloudWatch アラームで次のようなアラーム設定を行います。
- メトリクス名:windows_services_status
- InstanceId:対象 EC2 インスタンス ID
- service:対象のサービス名
- 統計:最小
- 期間:1分
- しきい値:windows_services_status <= 0
- アクション:通知アクションにてアラーム状態をトリガーとし、通知の送信先に SNS トピックを指定します。
サービスが起動中の状態以外を示す 0 が記録された場合をアラート条件とするため、メトリクス値が0以下としたしきい値を設定します。
やってみた
収集したカスタムメトリクスに対して CloudWatch アラームを設定し、サービス監視をやってみます。
カスタムメトリクスを収集している対象サービスを停止してみます。
Stop-Service Spooler
Get-Service Spooler
Status Name DisplayName
------ ---- -----------
Stopped Spooler Print Spooler
サービス停止によりメトリクス値がしきい値を下回ります。
しばらくすると CloudWatch アラームがアラート状態に変化しました。
SNS トピックに設定しているメールアドレス宛にもメールが届きました!
まとめ
CloudWatch エージェントの StatsD プロトコルを利用して、定期的にサービスの状態を示すカスタムメトリクスを送信してみました。
また、タスクスケジューラを利用することで、システム起動時にスクリプトを自動実行することもできます。
CloudWatch アラームの設定を行っておくことで、Windows サービスが停止した際に通知するといった仕組みを構築できると思います!
本記事が誰かのお役に立てれば幸いです。
参考